package com.hsc.www.plugin;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Properties;
import java.util.stream.Collectors;


@Intercepts({//注意看这个大花括号，也就这说这里可以定义多个@Signature对多个地方拦截，都用这个拦截器
        @Signature(type = Executor.class,//拦截接口
                method = "query",//拦截接口方法
                args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),//拦截接口方法参数列表
        @Signature(
                type = ParameterHandler.class,
                method = "setParameters",
                args = {PreparedStatement.class}),
        @Signature(
                type = StatementHandler.class,
                method = "prepare",
                args = {Connection.class, Integer.class}),
        @Signature(
                type = ResultSetHandler.class,
                method = "handleResultSets",
                args = {Statement.class})
})
public class ExamplePlugin implements Interceptor {
    // 这里是每次执行操作的时候，都会进行这个拦截器的方法内
    public Object intercept(Invocation invocation) throws Throwable {

        Object target = invocation.getTarget(); //被代理对象    对应@Signature中的type
        Method method = invocation.getMethod(); //代理方法      对应@Signature中的method
        Object[] args = invocation.getArgs();   //方法参数      对应@Signature中的args

        System.out.println("{");
        System.out.println("target:" + target.getClass().getSimpleName());
        System.out.println("method:" + method.getName());
        System.out.println("args:" + Arrays.toString(Arrays.stream(args).map(item ->
        {
            if (item != null) {
                return item.getClass().getSimpleName();
            } else {
                return null;
            }
        }).collect(Collectors.toList()).toArray()));
        System.out.println("}");


        // do something ...... 方法拦截前执行代码块
        Object result = invocation.proceed();
        // do something .......方法拦截后执行代码块
        return result;

    }

    // 插件初始化的时候调用，也只调用一次，插件配置的属性从这里设置进来
    public void setProperties(Properties properties) {

    }

    // 主要是为了把这个拦截器生成一个代理放到拦截器链中，
    public Object plugin(Object target) {
        //官方推荐写法，我们不要修改
        return Plugin.wrap(target, this);
    }
}
